package com.iwhalecloud.uncc.utils;

import com.iwhalecloud.uncc.common.ArchiverConstant;
import com.iwhalecloud.uncc.common.ArchiverThreadLocal;
import com.iwhalecloud.uncc.common.SysConstant;
import com.iwhalecloud.uncc.dao.ArchiverDao;
import com.iwhalecloud.uncc.db.DatasourceContextHolder;
import com.iwhalecloud.uncc.properties.UnccDsProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zq
 * @date 2021/10/22 11:34
 * @description DataSourceUtil
 */
@Component
@Slf4j
public class DataSourceUtil {
    @Autowired
    private UnccDsProperties unccDsProperties;

//    /**
//     * 反射轮询分片
//     * @param o
//     * @param method
//     * @return
//     */
//    public  List<T> roundRobinQuery(Object o,String method){
//        List<T> list = new ArrayList<>();
//        int num = ArchiverThreadLocal.getArchiveParam().getNumber();
//        try {
//            Method declaredMethod = o.getClass().getDeclaredMethod(method);
//            List<UnccDsProperties.UnccDsConfig> ucDataSourceList = getOnlineDatasource();
//            for (UnccDsProperties.UnccDsConfig unccDsConfig : ucDataSourceList) {
//                DatasourceContextHolder.setDs(unccDsConfig.getCode());
//                log.info("查询"+unccDsConfig.getCode()+"数据库");
//                list = Stream.of(list, (List<T>) declaredMethod.invoke(o))
//                        .flatMap(x -> x.stream()).collect(Collectors.toList());
//
////                list.addAll((List<T>) declaredMethod.invoke(o));
//
//                if(list.size() >= num){
//                    break;
//                }
//            }
//        }catch (Exception e){
//            log.error("roundRobinQuery 反射异常");
//            e.getStackTrace();
//
//        }finally {
//            DatasourceContextHolder.setDs(SysConstant.DB_DEFAULT_PARTITION);
//        }
////        return list;
////        return list.stream().sorted().limit(ArchiverThreadLocal.getArchiveParam().getNumber()).collect(Collectors.toList());
//        return list.stream().limit(num).collect(Collectors.toList());
//    }

    /**
     *
     * @param dao
     * @param o
     * @return
     */
    public List roundRobinQuery(ArchiverDao dao,Object o){
        List list = new ArrayList<>();
        int num = ArchiverThreadLocal.getArchiveParam().getNumber();
        List<UnccDsProperties.UnccDsConfig> ucDataSourceList = getOnlineDatasource();
        for (UnccDsProperties.UnccDsConfig unccDsConfig : ucDataSourceList) {
            DatasourceContextHolder.setDs(unccDsConfig.getCode());
            log.info("查询"+unccDsConfig.getCode()+"数据库");
            List list1 = dao.queryList(o);
            list = (List) Stream.of(list, list1).flatMap(x -> x.stream()).collect(Collectors.toList());
            if(list.size() >= num){
                break;
            }
        }
        DatasourceContextHolder.setDs(SysConstant.DB_DEFAULT_PARTITION);
        return (List) list.stream().limit(num).collect(Collectors.toList());
    }

    /**
     * 并行流轮询分片
     * @param dao
     * @param o
     * @return
     */
    public List roundRobinParallelQuery(ArchiverDao dao,Object o){
        List list = new ArrayList<>();
        int num = ArchiverThreadLocal.getArchiveParam().getNumber();
        List<UnccDsProperties.UnccDsConfig> ucDataSourceList = getOnlineDatasource();
        ucDataSourceList.parallelStream().forEach((u)-> {
            DatasourceContextHolder.setDs(u.getCode());
            log.info("查询" + u.getCode() + "数据库");
            list.addAll(dao.queryList(o));
            if (list.size() >num) {
                return ;
            }
        });
        DatasourceContextHolder.setDs(SysConstant.DB_DEFAULT_PARTITION);
        return (List) list.stream().limit(num).collect(Collectors.toList());
    }

    private List<UnccDsProperties.UnccDsConfig> getOnlineDatasource() {
        return unccDsProperties.getBizDatasource().stream().filter(i -> !i.getCode().startsWith(ArchiverConstant.HIS)).collect(Collectors.toList());
    }


}
